home *** CD-ROM | disk | FTP | other *** search
/ Info-Mac 3 / Info_Mac_1994-01.iso / Graphics / Utility / ARTAbrot 1.1 / BrotCode.c < prev    next >
Text File  |  1993-11-22  |  8KB  |  322 lines

  1. /************************************************************************/
  2. /*                                                                        */
  3. /*    FILE:        BrotCode.c -- Code for computing Mandelbrots.            */
  4. /*                                                                        */
  5. /*    PURPOSE:    Code to communicate with DSP to calculate Mandelbrots.    */
  6. /*                                                                        */
  7. /*    AUTHOR:        George T. Warner                                        */
  8. /*                                                                        */
  9. /*    REVISIONS:                                                            */
  10. /*    08/22/93    First version.                                            */
  11. /*                                                                        */
  12. /************************************************************************/
  13.  
  14. #include <Quickdraw.h>
  15. #include <stdlib.h>
  16. #include <stdio.h>
  17. #include <string.h>
  18. #include "DSPManager.h"
  19. #include "DSPConstants.h"
  20. #include "BrotCode.h"
  21. #include "ComUtil_ARTAbrot.h"    /* Common */
  22. #include "AB_Alert.h"
  23.  
  24. struct DSPCPUDeviceParamBlk pb, *pbPtr;
  25. DSPTaskRefNum taskRefNum;
  26. DSPModuleRefNum modRefNum;
  27. DSPSectionRefNum BroBufRefNum;
  28.  
  29. /* Offscreen pixMap stuff. */
  30. extern GWorldPtr offscreenGWorld;    /* Off screen graphics world. */
  31. extern Rect    GWorldBounds;            /* Boundaries of graphics world. */
  32.  
  33. int processing_brot = false;
  34. short *data_mem = nil;    /* Array for uploading Mandelbrot data into. */
  35. unsigned long ypoint;    /* Current y being processed. */
  36. int xpix, ypix;
  37. float fxdelta, fydelta;
  38. double distance_per_pixel, fheight;
  39.  
  40. #define NumElements 128L
  41.  
  42. typedef struct
  43. {
  44.     long Startflag;
  45.     long Doneflag;
  46.     long Points;
  47.     long Maxiter;
  48.     float Xstart;
  49.     float Delta;
  50.     float Ystart;
  51.     long Inited;
  52.     short OutputData[640];
  53. }
  54. MyPBuff;
  55.  
  56. MyPBuff *mypbuffptr;
  57.  
  58.  
  59. pascal void fatalError(DSPMessagePtr errorBlockPtr)
  60. {
  61. #pragma unused (errorBlockPtr)
  62. char tmp_string[256];
  63.  
  64.     sprintf(tmp_string, "MessageActionProc called.");
  65.     AB_Alert(tmp_string);
  66. }
  67.  
  68. void start_brot()
  69. {
  70. char tmp_string[256];
  71. OSErr err;
  72.     
  73.     SetPort(WPtr_ARTAbrot);
  74.  
  75.     /* Get width of image to calculate. */
  76.     xpix = (WPtr_ARTAbrot->portRect.right-WPtr_ARTAbrot->portRect.left)-SCROLLBARWIDTH;
  77.     /* Get height of image to calculate. */
  78.     ypix = (WPtr_ARTAbrot->portRect.bottom-WPtr_ARTAbrot->portRect.top)-SCROLLBARWIDTH;
  79.     /* Find the distance between pixels. */
  80.     distance_per_pixel = fwidth/(double)xpix;
  81.     /* Find the height of the image. */
  82.     fheight = (double)ypix * distance_per_pixel;
  83.  
  84.     pb.pbhDeviceIndex        = 0;                    /* Just use device 0. */
  85.     pb.pbhClientPermission    = kdspReadPermission;    /* Not sure what this means. */
  86.     pb.pbhDeviceICON        = nil;                    /* No icon desired. */
  87.     pb.pbhClientICON         = nil;
  88.     pb.cpuClientMessageActionProc = fatalError;
  89.     BlockMove("\pARTAbrot", pb.pbhClientName, 32);
  90.     
  91.     pbPtr = &pb;
  92.     
  93.     /* Get information on DSP 0. */
  94.     if (DSPGetIndexedCPUDevice(pbPtr)) {
  95.         sprintf(tmp_string, "Failure: No DSPs attached!");
  96.         AB_Alert(tmp_string);
  97.         return;
  98.     }
  99.  
  100.     /* Open device driver. */
  101.     if (DSPOpenCPUDevice(pbPtr)) {
  102.         sprintf(tmp_string, "Failure opening DSP device driver.");
  103.         AB_Alert(tmp_string);
  104.         return;
  105.     }
  106.     
  107.     /* Create a new task structure. */
  108.     if (DSPNewTask(pbPtr, &fatalError, "\pMandelbrot", &taskRefNum)) {
  109.         sprintf(tmp_string, "Failure creating new task structure.");
  110.         AB_Alert(tmp_string);
  111.         goto close_device;
  112.     }
  113.  
  114.     /* Load a module into the task structure. */
  115.     err = DSPLoadModule("\pmbrot",     /* Load MBrot resource. */
  116.                     taskRefNum,     /* Pass task structure reference number. */
  117.                     kdspAnyPositionInsert, /* Put it anywhere. */
  118.                     (DSPModuleRefNum)NULL,     /* Optional reference module number. */
  119.                     &modRefNum,     /* Pointer to get module reference number. */
  120.                     NumElements);    /* Scale multiplier (not sure about this yet). */
  121.     if (err) {
  122.         sprintf(tmp_string, "Failure loading MBrot module.");
  123.         AB_Alert(tmp_string);
  124.         goto dispose_task;
  125.     }
  126.  
  127.     /* Insert Task into Task List */
  128.     if (DSPInsertTask(pbPtr, taskRefNum, kdspAnyPositionInsert, kdspTimeShare, (DSPTaskRefNum)NULL)) {
  129.         sprintf(tmp_string, "Failure inserting task.");
  130.         AB_Alert(tmp_string);
  131.         goto dispose_task;
  132.     }
  133.  
  134.     /* Get section reference numbers for the parameter buffer. */
  135.     if (DSPGetSection(modRefNum,"\pbrobuf",&BroBufRefNum)) {
  136.         sprintf(tmp_string, "Failure getting parameter buffer reference number.");
  137.         AB_Alert(tmp_string);
  138.         goto remove_task;
  139.     }
  140.  
  141.     /* Get pointer to parameter buffer. */
  142.     err = DSPGetSectionData(BroBufRefNum,(Ptr *)&mypbuffptr);
  143.     if (err) {
  144.         sprintf(tmp_string, "Failure getting parameter buffer pointer.");
  145.         AB_Alert(tmp_string);
  146.         goto remove_task;
  147.     }
  148.  
  149.     /* Allocate buffer to hold one line of data. */
  150.     data_mem = (short *)calloc(xpix, sizeof(short));
  151.     if(!data_mem) {
  152.         sprintf(tmp_string, "Failure allocating data buffer.");
  153.         AB_Alert(tmp_string);
  154.         goto remove_task;
  155.     }
  156.  
  157.     fydelta = fxdelta = fwidth/xpix;
  158.     /* Download left coordinate of image. */
  159.     mypbuffptr->Xstart = fxcenter-(fwidth/2);
  160.     mypbuffptr->Delta = fxdelta;
  161.     /* Download bottom coordinate of image. */
  162.     mypbuffptr->Ystart = fycenter-(fheight/2);
  163.     /* Tell num. of pixels to do. */
  164.     mypbuffptr->Points = xpix;
  165.     mypbuffptr->Maxiter = fiters;
  166.     /* Start with first line. */
  167.     mypbuffptr->Doneflag = 0;
  168.     mypbuffptr->Startflag = 0;
  169.  
  170.     /* Start calculations! */
  171.     if (DSPSetTaskActive(taskRefNum)) {
  172.         sprintf(tmp_string, "Failure setting task active.");
  173.         AB_Alert(tmp_string);
  174.         goto quit_task;
  175.     }
  176.  
  177.     /* Wait for DSP module to initialize. */
  178.     while (!mypbuffptr->Inited) {
  179.         /* Force stop waiting if user hits command-period. */
  180.         if (check_stop()) {
  181.             goto quit_task;
  182.         }
  183.     }
  184.  
  185.     /* Start processing first line. */
  186.     mypbuffptr->Startflag = 1;
  187.     ypoint = 0;
  188.     processing_brot = true;
  189.  
  190.     return;
  191.  
  192.  
  193. quit_task:
  194.     if (data_mem)
  195.         free(data_mem);
  196.  
  197. remove_task:
  198.     /* Remove the Task */
  199.     if (DSPRemoveTask(taskRefNum)) {
  200.         ShowCursor();
  201.         sprintf(tmp_string, "Failure removing task.");
  202.         AB_Alert(tmp_string);
  203.     }
  204.  
  205. dispose_task:
  206.     /* Dispose the Task */
  207.     if (DSPDisposeTask(taskRefNum)) {
  208.         ShowCursor();
  209.         sprintf(tmp_string, "Failure disposing task.");
  210.         AB_Alert(tmp_string);
  211.     }
  212.  
  213. close_device:
  214.     /* Close the CPU Device */
  215.     if (DSPCloseCPUDevice(pbPtr)) {
  216.         ShowCursor();
  217.         sprintf(tmp_string, "Failure closing DSP driver.");
  218.         AB_Alert(tmp_string);
  219.     }
  220.  
  221.     new_coordinates=FALSE;
  222.     ShowCursor();
  223. }
  224.  
  225. void continue_brot()
  226. {
  227. Ptr base_addr;
  228. long row_bytes;    /* Used for PixMap calculations. */
  229. Rect rect_to_copy;
  230. unsigned char *pixel_address;
  231. long xpoint;
  232.     
  233.     if (!mypbuffptr->Doneflag) {
  234.         /* If no data to process, just return. */
  235.         return;
  236.     }
  237.  
  238.     SetPort(WPtr_ARTAbrot);
  239.  
  240.     /* Lock the offscreen GWorld. */
  241.     LockPixels(offscreenGWorld->portPixMap);
  242.     row_bytes = ((**(offscreenGWorld->portPixMap)).rowBytes) & 0x3fff;
  243.     base_addr = GetPixBaseAddr(offscreenGWorld->portPixMap);
  244.  
  245.     /* Copy data from DSP buffer. */
  246.     BlockMove(mypbuffptr->OutputData, data_mem, xpix * sizeof(short));
  247.  
  248.     ypoint++;
  249.  
  250.     if (ypoint != ypix) { /* Don't start new line if we don't need it. */
  251.         /* Download new Y coordinate. */
  252.         mypbuffptr->Ystart = (fycenter-(fheight/2)) + (ypoint * fxdelta);
  253.         /* Acknowledge that last line was completed. */
  254.         mypbuffptr->Doneflag = 0;
  255.         /* Tell it to go. */
  256.         mypbuffptr->Startflag = 1;
  257.     }
  258.  
  259.     /* Convert results to bytes for indexed color display. */
  260.     pixel_address = (unsigned char *)((unsigned long)base_addr + ((ypoint-1) * (unsigned long)row_bytes));
  261.     for (xpoint=0; xpoint < xpix; xpoint++)
  262.         *pixel_address++ = data_mem[xpoint];
  263.  
  264.     SetRect(&rect_to_copy, GWorldBounds.left, GWorldBounds.top+ypoint-1, GWorldBounds.right, GWorldBounds.top+ypoint); /* left, top, right, bottom */
  265.  
  266.     /* Display line on screen. */
  267.     CopyBits((BitMap *)*offscreenGWorld->portPixMap, &(WPtr_ARTAbrot->portBits), &(rect_to_copy), &(rect_to_copy), srcCopy, 0);
  268.  
  269.     UnlockPixels(offscreenGWorld->portPixMap);
  270.  
  271.     if (ypoint == ypix) {
  272.         /* If we are done, clean up. */
  273.         finish_brot();
  274.     }
  275. }
  276.  
  277.  
  278. void finish_brot()
  279. {
  280. char tmp_string[256];
  281.  
  282.     processing_brot = false;
  283.     
  284.     while (!mypbuffptr->Doneflag) {
  285.         /* Wait for last line to complete. */
  286.         if (check_stop()) {
  287.             /* If we can't wait or are hung, just get out. */
  288.             goto get_out_hard_way;
  289.         }
  290.     }
  291.  
  292. get_out_hard_way:
  293.     if (data_mem)
  294.         free(data_mem);
  295.  
  296.     /* Remove the Task */
  297.     if (DSPRemoveTask(taskRefNum)) {
  298.         ShowCursor();
  299.         sprintf(tmp_string, "Failure removing task.");
  300.         AB_Alert(tmp_string);
  301.     }
  302.  
  303.     /* Dispose the Task */
  304.     if (DSPDisposeTask(taskRefNum)) {
  305.         ShowCursor();
  306.         sprintf(tmp_string, "Failure disposing task.");
  307.         AB_Alert(tmp_string);
  308.     }
  309.  
  310.     /* Close the CPU Device */
  311.     if (DSPCloseCPUDevice(pbPtr)) {
  312.         ShowCursor();
  313.         sprintf(tmp_string, "Failure closing DSP driver.");
  314.         AB_Alert(tmp_string);
  315.     }
  316.  
  317.     new_coordinates=FALSE;
  318. }
  319.  
  320.  
  321.  
  322.